package pl.ps.wi.monitoring.station.services;

import java.nio.Buffer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.io.BufferedReader;

import pl.ps.wi.monitoring.station.interfaces.PinEnterListener;
/**
* @brief Zawiera definicję klasy KeyboardService. Moduł odpowiedzialny za obsługę klawiatury.
* @date 24.03.2010
* @version 1.0
*/

/**
* @class KeyboardService
* Klasa służąca do obsługi klawiatury. Obsługuje klawiaturę, której używa się do uwierzytelniania osoby poprzez podanie kodu.\n
* Posiada nastepujace pola: {@link KeyboardService::thread thread}, {@link KeyboardService::interupt interupt}, {@link KeyboardService::listeners listeners}.\n
* Posiada nastepujace metody: {@link KeyboardService::KeyboardService() KeyboardService()}, {@link KeyboardService::addPinEnterListener(PinEnterListener) addPinEnterListener(PinEnterListener)},
*{ @link KeyboardService::removePinEnterListener(PinEnterListener) removePinEnterListener(PinEnterListener)}, {@link KeyboardService::listen() listen()}, {@link KeyboardService::interupt() interupt()}.
*/
public class KeyboardService {
	/**
	* Obiekt final typu Thread. Służy do obsługi wątka powstającego w czasie tworzenia obiektu tej klasy i obsługujący wątek.\n
	*/
	private final Thread thread;
	
	/**
	* Pole logiczne interupt. Zainicjowane jako flase. Służy do obsługi przerwań wątku sterującego obsługą.
	*/
	private boolean interupt = false;
	
	/**
	* Kolekcja obiektów oczekujących zdarzenia PinEnterListener
	*/
	private final List<PinEnterListener> listeners;
	/**
	* Konstruktor domyślny klasy KeyboardService. 
	* Tworzy nowy obiekt klasy. Skanuje standardowe wejście. Czeka na interupt. Tworzy listę PinEnterListener. 
	*/
	public KeyboardService() {
		Runnable child = new Runnable() {
			@Override
			public void run() {
				Scanner scanner = new Scanner(System.in);

				while(!interupt && !scanner.hasNextLine()) {
					continue;
				}
				if (!interupt) {
					String pin = scanner.nextLine();
					// inform all listeners
					for (PinEnterListener listener : listeners) {
						listener.onPinEnter(pin);
					}
				}
			}
		};
		thread = new Thread(child, "keyboard service");
		
		listeners = new ArrayList<PinEnterListener>();
	}
	/**
	* Metoda dodająca obiekty do listy listeners.
	* @param listener
	* @see listeners
	*/
	public void addPinEnterListener(PinEnterListener listener) {
		listeners.add(listener);
	}
	/**
	* Metoda usuwająca obiekty z listy listeners.
	* @param listener
	* @see listeners
	*/
	public void removePinEnterListener(PinEnterListener listener) {
		listeners.remove(listener);
	}
	/**
	* Metoda uruchamiająca wątek thread. Zaczyna nasłuchwanie.
	* @see thread
	*/
	public void listen() {
		thread.start();
	}
	/**
	* Obsługa przerwania wątku KeyboardService. Służy do ustawienia zmiennej interupt na true. Dodatkowo czeka na zakończenie innych wątków.
	* @see interupt
	*/
	public void interupt() {
		interupt = true;
		if (thread != null) {
			thread.interrupt();
			try { // wait for thread
				thread.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}
